<?php

class Criterii {
    const DEBRANSAT='-';
    const PAUSAL='*';

    /** ID-urile criteriilor */
    static $criterii = array(
        1   =>  'apa_calda',
        2   =>  'apa_rece',
        3   =>  'benef',
        4   =>  'egal',
        5   =>  'consum_ac',
        6   =>  'consum_ar',
//        7   =>  'en_term',
        8   =>  'nr_apom_ar',
        9   =>  'nr_apom_ac',
        10  =>  'pers',
        11  =>  'set',
        12  =>  'supr',
        13  =>  'nr_rep',
        14  =>  'nr_elem'
    );

    /** Impartirea proportionala a unei valori
    * @param number $valoare
    * @param array $target
    * @return array
    */
    static function divide($valoare, array $target) {
        // $target: [id_spatiu => valoare pondere]
        // se insumeaza ponderile
        $total = array_sum($target);
        // daca totalul este nul, rezultatul este nul
        if (!$total)
            return array_fill_keys(array_keys($target), null);
        // valoarea se repartizeaza proportional in functie de ponderi
        foreach ($target as $id => $pondere) {
            $result[$id] = $pondere*$valoare/$total;
        }
        return (array)$result;
    }

    static function getProperty($id, $property) {
        $class = self::$criterii[$id];
        $propertyObject = new ReflectionProperty($class, $property);
        return $propertyObject->getValue();
    }

    static function callMethod($id, $method, array $arguments = array()) {
        $class = self::$criterii[$id];
        $methodObject = new ReflectionMethod($class, $method);
        return $methodObject->invokeArgs(null, $arguments);
    }


}


abstract class Criteriu_ {
    /** parametrii apartamentelor care sunt necesari criteriului (in aceasta situatie nu este decat unul singur); sunt de forma ( parametru => descriere ); se defineste in clasele derivate */
    static $parametriApartament = array();
    /** descrierea criteriului (apare in pagina HTML); se defineste in clasele derivate */
    static $text = '';
    /** parametrul poate fi lunar (de ex. consumurile) sau nu */
    static $monthly = false;
}

abstract class CriteriuSimplu extends Criteriu {
    // aceasta functie trebuie sa fie declarata si in clasele derivate
    static function execute($valoare, array $target, $month) {
        // `target` contine ID-urile apartamentelor
        // construiesc un array asociativ: ID apartament => valoarea parametrului specific apartamentului
        $fullTarget=array();
        // preiau valorile parametrilor specifici apartamentelor
        foreach ($target as $id) {
            $parametru = key(reset(lateStaticBinding_method('getParametriApartament')));
            $fullTarget[$id] = Apartamente::getParametru($id, $parametru, $month);
        }
        // efectuez calculele
        $result=array();
        $result[0]=array(
            'valuable'=>true,
            'target'=>Criterii::divide($valoare, $fullTarget)
        );
        return $result;
    }
}

class pers extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>'Nr. persoane');
    static $text = "după nr. de persoane";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class supr extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>"Suprafaţa utilă");
    static $text = "după suprafaţa utilă";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class nr_apom_ar extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>"Nr. apometre pt. apa rece");
    static $text = "după nr. de apometre pt. apa rece";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class nr_apom_ac extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>"Nr. apometre pt. apa caldă");
    static $text = "după nr. de apometre pt. apa caldă";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class SET extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>'S.E.T.');
    static $text = "după S.E.T.";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class consum_ar extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>"Consum de apă rece");
    static $text = "după consumul de apă rece";
    static $monthly = true;
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class consum_ac extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>"Consum de apă caldă");
    static $text = "după consumul de apă caldă";
    static $monthly = true;
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class nr_elem extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>'Numărul total de elemenţi');
    static $text = "după numărul total de elemenţi";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class nr_rep extends CriteriuSimplu {
    static $parametriApartament = array(__CLASS__=>'Numărul de repartitoare');
    static $text = "după numărul de repartitoare";
    static function execute($valoare, array $target, $month) {
        return parent::execute($valoare, $target, $month);
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class egal extends Criteriu {
    static $text = "în mod egal";

    static function execute($valoare, array $target, $month) {
        // efectuarea calculelor
        $part = $valoare/count($target);
        $res = array();
        foreach ($target as $id) $res[$id]=$part;
        // crearea rezultatului
        $result=array();
        $result[0]=array(
            'valuable'=>true,
            'target'=>$res
        );
        return $result;
    }
    static function getParametriApartament() {
        return self::$parametriApartament;
    }
}

class benef extends Criteriu {
    static $text = "pe beneficiar";

    static function getParametriApartament() {
        return self::$parametriApartament;
    }

    static function execute($valoare, array $target, $month, array $cote) {
        // crearea rezultatului
        $result = array();
        $result[0]=array(
            'valuable'=>true,
            'target'=>$cote
        );
        return $result;
    }

    static function getFragmentParams() { ?>
        <div id="cr_<?=__CLASS__?>">
            se vor specifica, pentru fiecare apartament din TARGET, sumele ce se repartizeaza la fiecare
        </div>
        <script type="text/javascript">
            var cp = $('#cr_<?=__CLASS__?>');
            CriteriiParams['<?=array_search(__CLASS__, Criterii::$criterii)?>'] = cp;

            cp.duplicate(function(){
                var $clone = this;

                $clone.data('fn_parametri', function(){
                    return 'paişpe';
                });
            });
        </script> <?php
    }
}


abstract class apa extends Criteriu {

    const CANTITATE_FACTURATA = 'f';
    const CANTITATE_COMUN = 'c';
    const PIERDERI = 'p';
    const DIFERENTE = 'd';
    const DOUA_FACTURI = 'df';

    /** Corespondenta dintre constantele simbolice folosite in pagina HTML si constantele folosite in program */
    static $map = array(
        CANTITATE_FACTURATA_HTML => self::CANTITATE_FACTURATA,
        CANTITATE_COMUN_HTML => self::CANTITATE_COMUN,
        PIERDERI_HTML => self::PIERDERI,
        DIFERENTE_HTML => self::DIFERENTE,
        DOUA_FACTURI_HTML => self::DOUA_FACTURI
    );

    static function getParametriApartament($parametriCriteriu) {
        $parametriApartament = array();

        $pierderi = $parametri[self::PIERDERI]; // pierderi masurabile
        $diferente = $parametri[self::DIFERENTE]; // modul de repartizare al diferentelor de citire
        $cantitate = $parametri[self::CANTITATE_FACTURATA]; // cantitatea facturata  !! ATENTIE: trebuie sa fie diferita de 0
        $cantitateComun = $parametri[self::CANTITATE_COMUN]; // cantitatea consumata pentru spatiile comune

        // daca exista pierderi sau cantitate consumata de pe spatiul comun, acestea se repartizeaza functie de suprafata utila (cota-parte)
        if ($pierderi || $cantitateComun)
            $parametriApartament+= Criterii::callMethod(12, 'getParametriApartament');

        $cantitateDeclarata = 0;
        $mainParametru = Criterii::callMethod(lateStaticBinding_property('mainParametruApartament'), 'getParametriApartament');
        $parametru = key(reset($mainParametru));
        foreach ($target as $id) {
            $consum = Apartamente::getParametru($id, $parametru, $month);
            if ($consum===Criterii::DEBRANSAT) {
                $targetDebransat = true;
            } elseif ($consum===Criterii::PAUSAL) {
                $targetPausal = true;
            } else {
                $targetContorizat = true;
                $cantitateDeclarata+= $consum;
            }
        }

        // daca exista apart. necontorizate si cantitatea facturata este diferita de cantitatea totala declarata (pentru apart contorizate), atunci este nevoie de numarul de persoane
        if ($targetPausal) {
            if ($cantitate != $cantitateDeclarata)
                $parametriApartament+= Criterii::callMethod(10, 'getParametriApartament');
        } else {
        // daca nu exista apart. necontorizate:
            // daca exista apart. contorizate si cantitatea facturata este diferita de cantitatea totala declarata, atunci este nevoie de parametrul solicitat de criteriul pentru repartizarea diferentelor de citire
            if ($targetContorizat) {
                if ($cantitate != $cantitateDeclarata)
                    $parametriApartament+= Criterii::callMethod($diferente, 'getParametriApartament');
            } else
            // daca toate apart. sunt debransate, este necesara suprafata utila a fiecarui apart.
                $parametriApartament+= Criterii::callMethod(12, 'getParametriApartament');
        }

        $parametriApartament+= $mainParametru;

        return $parametriApartament;
    }

    static function execute($valoare, array $target, $month, array $parametri) {
        $pierderi = $parametri[self::PIERDERI]; // pierderi masurabile
        $diferente = $parametri[self::DIFERENTE]; // modul de repartizare al diferentelor de citire
        $cantitate = $parametri[self::CANTITATE_FACTURATA]; // cantitatea facturata  !! ATENTIE: trebuie sa fie diferita de 0
        $cantitateComun = $parametri[self::CANTITATE_COMUN]; // cantitatea consumata pentru spatiile comune

        // formatarea rezultatului partial
        $result=array();
        $result['valoare_pierderi']=array();
        $result['cantitate_pierderi']=array();
        $result['valoare_consum']=array();
        $result['cantitate_consum']=array();
        $result['valoare_diferente']=array();
        $result['cantitate_diferente']=array();
        $result['valoare_comun']=array();
        $result['cantitate_comun']=array();

        // calculez pretul unitar pe mc de apa
        $pretUnitar = $valoare/$cantitate;
        // scad valoarea pierderilor din valoarea facturata
        $valoare-= $pierderi*$pretUnitar;
        // scad pierderile din cantitatea totala
        $cantitate-= $pierderi;
        // scad valoarea cantitatatii pentru spatiul comun din valoarea facturata (ce a mai ramas)
        $valoare-=$cantitateComun*$pretUnitar;
        // scad cantitatea pentru spatiul comun din cantitatea totala
        $cantitate-=$cantitateComun;

        // repartizare pierderi; se aplica pentru toata lista
        if ($pierderi) {
            // pierderile se repartizeaza in functie de suprafata (cota-parte)
            $res = Criterii::callMethod(12, 'execute', array($pierderi*$pretUnitar, $target, $month));
            $result['valoare_pierderi'] = $res[0]['target'];
            $res = Criterii::callMethod(12, 'execute', array($pierderi, $target, $month));
            $result['cantitate_pierderi'] = $res[0]['target'];
        }

        // repartizare cantitate pt spatiul comun
        if ($cantitateComun) {
            $res = Criterii::callMethod(12, 'execute', array($cantitateComun*$pretUnitar, $target, $month));
            $result['valoare_comun'] = $res[0]['target'];
            $res = Criterii::callMethod(12, 'execute', array($cantitateComun, $target, $month));
            $result['cantitate_comun'] = $res[0]['target'];
        }

        // extrag din lista apartamentele si le grupez: debransate, necontorizate, contorizate
        $targetDebransat=array();
        $targetContorizat=array();
        $targetPausal=array();
        $cantitateDeclarata = 0;
        // citesc si analizez consumul de la fiecare apartament
        $mainParametru = lateStaticBinding_property('mainParametruApartament');
        $parametru = key(reset(Criterii::callMethod($mainParametru, 'getParametriApartament')));
        foreach ($target as $id) {
            $consum = Apartamente::getParametru($id, $parametru, $month);
            if ($consum===Criterii::DEBRANSAT) {
                $targetDebransat[] = $id;
                $result['cantitate_consum'][$id] = $consum;
            } elseif ($consum===Criterii::PAUSAL) {
                $targetPausal[] = $id;
            } else {
                $targetContorizat[] = $id;
                $cantitateDeclarata+= $consum;
            }
        }

        // repartizez cantitatea declarata la apartamentele contorizate
        if ($targetContorizat) {
            $res = Criterii::callMethod($mainParametru, 'execute', array($cantitateDeclarata*$pretUnitar, $targetContorizat, $month));
            $result['valoare_consum']+= $res[0]['target'];
            $res = Criterii::callMethod($mainParametru, 'execute', array($cantitateDeclarata, $targetContorizat, $month));
            $result['cantitate_consum']+= $res[0]['target'];
        }

        // repartizez cantitatea ramasa la apartamentele necontorizate
        if ($targetPausal) {
            if ($cantitate != $cantitateDeclarata) {
                $res = Criterii::callMethod(10, 'execute', array( ($cantitate-$cantitateDeclarata)*$pretUnitar, $targetPausal, $month));
                $result['valoare_consum']+= $res[0]['target'];
                $res = Criterii::callMethod(10, 'execute', array($cantitate-$cantitateDeclarata, $targetPausal, $month));
                $result['cantitate_consum']+= $res[0]['target'];
            }
        } else {
            // repartizez cantitatea ramasa, adica diferentele de citire, la spatiile contorizate
            if ($targetContorizat) {
                if ($cantitate!=$cantitateDeclarata) {
                    $res = Criterii::callMethod($diferente, 'execute', array( ($cantitate-$cantitateDeclarata)*$pretUnitar, $targetContorizat, $month));
                    $result['valoare_diferente'] = $res[0]['target'];
                    $res = Criterii::callMethod($diferente, 'execute', array($cantitate-$cantitateDeclarata, $targetContorizat, $month));
                    $result['cantitate_diferente'] = $res[0]['target'];
                }
            } else {
                // exista doar apart. debransate
                $res = Criterii::callMethod(12, 'execute', array($cantitate*$pretUnitar, $targetDebransat, $month));
                $result['valoare_comun']+= $res[0]['target'];
                $res = Criterii::callMethod(12, 'execute', array($cantitate, $targetDebransat, $month));
                $result['cantitate_comun']+= $res[0]['target'];
            }
        }

        // creez cele doua subcoloane: consum si valoare
        $subcoloanaConsum=array();
        $subcoloanaValoare=array();
        // determin daca se recalculeaza consumul
        if ($pierderi || $cantitateComun || (!$targetPausal && $cantitate!=$cantitateDeclarata)) $c=" indiv./calculat";
        // completez cele doua subcoloane
        foreach ($target as $id) {
            $consumIndividual=$result['cantitate_consum'][$id];
            // consumul individual se rotunjeste la o zecimala
            if (is_numeric($consumIndividual)) $consumIndividual=round($consumIndividual, 1);
            // consumurile in regim pausal vor avea un semn distinctiv
            if (in_array($id, $targetPausal)) $consumIndividual.=Criterii::PAUSAL;
            // completez coloana de consum
            $subcoloanaConsum[$id]=$consumIndividual;
            // daca se recalculeaza consumul, vor fi afisate si consumul individual, si cel recalculat
            if ($c) {
                $consumCalculat  = $consumIndividual+$result['cantitate_pierderi'][$id] + $result['cantitate_diferente'][$id] + $result['cantitate_comun'][$id];
                $subcoloanaConsum[$id].=' / '.round($consumCalculat, 1);
            }
            // completez coloana valorica
            $subcoloanaValoare[$id] = $result['valoare_consum'][$id] + $result['valoare_pierderi'][$id] + $result['valoare_diferente'][$id] + $result['valoare_comun'][$id];
        }
        // creez rezultatul final
        $result=array();
        $result["consum$c"]=array(
            'valuable'=>false,
            'target'=>$subcoloanaConsum
        );
        $result["valoare"]=array(
            'valuable'=>true,
            'target'=>$subcoloanaValoare
        );
        return $result;
    }
}

class apa_rece extends apa {
    static $mainParametruApartament = 6;
    static $text = "după consumul de apă rece";
    static $criteriiDiferente = array(6, 10, 12);

    static function getParametriApartament() {
        return parent::getParametriApartament();
    }

    static function getFragmentParams() {
        // continutul HTML pentru modurile de repartizare a diferentelor
        $diferenteHTML = '';
        foreach (self::$criteriiDiferente as $idCriteriu)
            $diferenteHTML.= sprintf(OPTION_HTML, $idCriteriu, Criterii::getProperty($idCriteriu, 'text')); ?>

        <div id="cr_<?=__CLASS__?>">
            <form action="javascript:void(0)">
                <ul class="note-brown mt-m">
                    <li>în afară de <i>cantitatea facturată</i> (care este obligatorie), celelalte informaţii se completează doar dacă este cazul.</li>
                    <li>dacă în această factură este inclusă şi apa rece folosită pentru prepararea apei calde, se va înregistra toată cantitatea facturată (apă rece + apă caldă); cantitatea de apă caldă consumată se va specifica odată cu înregistrarea facturii pentru energia termică folosită la prepararea acesteia.</li>
                </ul>
                <table class="form mt-m">
                    <tr>
                        <td>Cantitate facturată [m³]</td>
                        <td><input class="half" type="text" name="<?=CANTITATE_FACTURATA_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Cantitate consumată<br>pe spaţiile comune [m³]</td>
                        <td><input class="half" type="text" name="<?=CANTITATE_COMUN_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Pierderi [m³]</td>
                        <td><input class="half" type="text" name="<?=PIERDERI_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Modul de repartizare<br>a diferenţelor de citire</td>
                        <td><select name="<?=DIFERENTE_HTML?>"><?=$diferenteHTML?></select></td>
                    </tr>
                </table>
            </form>
        </div>
        <script type="text/javascript">
            var cp = $('#cr_<?=__CLASS__?>');
            CriteriiParams['<?=array_search(__CLASS__, Criterii::$criterii)?>'] = cp;

            cp.duplicate(function(){
                var $clone = this;

                $clone.data('fn_parametri', function(){
                    return arrayValues($clone.find('form').serializeArray());
                });
            });
        </script> <?php
    }

    static function checkFields(array &$fields) {
        // - CANTITATE_FACTURATA
        $field = self::CANTITATE_FACTURATA;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        // trebuie sa fie specificata
        if (!$length) $e = FILL;
        // sa fie numar
        elseif (!isFloat($value)) $e = USE_FLOAT;
        // sa fie incadrat intr-un anumit interval
        elseif (!checkNumberLength($value)) $e = TOO_BIG;
        // sa nu fie nul
        elseif (!(float)$value) $e = NOT_ZERO;
        ####
        if ($e) $errors[$field]=$e;

        // - CANTITATE_COMUN (optional)
        $field = self::CANTITATE_COMUN;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        if ($length) {
            // sa fie numar
            if (!isFloat($value)) $e = USE_FLOAT;
            // sa fie incadrat intr-un anumit interval
            elseif (!checkNumberLength($value)) $e = TOO_BIG;
            // daca valoarea este nula, parametrul se elimina
            elseif (!$value) unset($fields[$field]);
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        // - PIERDERI (optional)
        $field = self::PIERDERI;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        if ($length) {
            // sa fie numar
            if (!isFloat($value)) $e = USE_FLOAT;
            // sa fie incadrat intr-un anumit interval
            elseif (!checkNumberLength($value)) $e = TOO_BIG;
            // daca valoarea este nula, parametrul se elimina
            elseif (!$value) unset($fields[$field]);
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        // - DIFERENTE (optional)
        $field = self::DIFERENTE;
        $value = &$fields[$field];
        $length=length($value);
        $e=null;
        if ($length) {
            // modul de repartizare sa fie valid
            if (!in_array($value, self::$criteriiDiferente)) $e = "Specificaţi modul de repartizare a diferenţelor de citire !";
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        return $errors;
    }
}

class apa_calda extends apa {
    static $mainParametruApartament = 5;
    static $text = "după consumul de apă caldă";
    static $criteriiDiferente = array(5, 10, 12);

    static function getParametriApartament() {
        return parent::getParametriApartament();
    }

    static function getFragmentParams() {
        // continutul HTML pentru modurile de repartizare a diferentelor
        $diferenteHTML = '';
        foreach (self::$criteriiDiferente as $idCriteriu)
            $diferenteHTML.= sprintf(OPTION_HTML, $idCriteriu, Criterii::getProperty($idCriteriu, 'text')); ?>

        <div id="cr_<?=__CLASS__?>">
            <form action="javascript:void(0)">
                <ul class="note-brown">
                    <li>pentru apa caldă pot fi emise două facturi (caz în care se va bifa căsuţa de mai jos), una pentru apa rece folosită la prepararea apei calde, iar cealaltă pentru energia termică folosită la încălzirea acesteia</li>
                    <li>aici se înregistrează factura pentru energia termică folosită pentru încălzirea apei, indiferent dacă aceasta include sau nu preţul apei recei folosite la prepararea apei calde</li>
                    <li>în afară de <i>cantitatea facturată</i> (care este obligatorie), celelalte informaţii se completează doar dacă este cazul</li>
                </ul>
                <div class="mt-m">
                    <label><input type="checkbox" name="<?=DOUA_FACTURI_HTML?>"><b>sunt emise două facturi</b></label>
                </div>
                <table class="form mt-m">
                    <tr>
                        <td>Cantitate facturată [m³]</td>
                        <td><input class="half" type="text" name="<?=CANTITATE_FACTURATA_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Cantitate consumată<br>pe spaţiile comune [m³]</td>
                        <td><input class="half" type="text" name="<?=CANTITATE_COMUN_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Pierderi [m³]</td>
                        <td><input class="half" type="text" name="<?=PIERDERI_HTML?>"></td>
                    </tr>
                    <tr>
                        <td>Modul de repartizare<br>a diferenţelor de citire</td>
                        <td><select name="<?=DIFERENTE_HTML?>"><?=$diferenteHTML?></select></td>
                    </tr>
                </table>
            </form>
        </div>
        <script type="text/javascript">
            var cp = $('#cr_<?=__CLASS__?>');
            CriteriiParams['<?=array_search(__CLASS__, Criterii::$criterii)?>'] = cp;

            cp.duplicate(function(){
                var $clone = this;

                $clone.data('fn_parametri', function(){
                    return arrayValues($clone.find('form').serializeArray());
                });
            });
        </script> <?php
    }

    static function checkFields(array &$fields) {
        // - CANTITATE_FACTURATA
        $field = self::CANTITATE_FACTURATA;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        // trebuie sa fie specificata
        if (!$length) $e = FILL;
        // sa fie numar
        elseif (!isFloat($value)) $e = USE_FLOAT;
        // sa fie incadrat intr-un anumit interval
        elseif (!checkNumberLength($value)) $e = TOO_BIG;
        // sa nu fie nul
        elseif (!(float)$value) $e = NOT_ZERO;
        ####
        if ($e) $errors[$field]=$e;

        // - CANTITATE_COMUN (optional)
        $field = self::CANTITATE_COMUN;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        if ($length) {
            // sa fie numar
            if (!isFloat($value)) $e = USE_FLOAT;
            // sa fie incadrat intr-un anumit interval
            elseif (!checkNumberLength($value)) $e = TOO_BIG;
            // daca valoarea este nula, parametrul se elimina
            elseif (!$value) unset($fields[$field]);
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        // - PIERDERI (optional)
        $field = self::PIERDERI;
        $value = &$fields[$field];
        checkScalar($value, true);
        $length=length($value);
        $e=null;
        if ($length) {
            // sa fie numar
            if (!isFloat($value)) $e = USE_FLOAT;
            // sa fie incadrat intr-un anumit interval
            elseif (!checkNumberLength($value)) $e = TOO_BIG;
            // daca valoarea este nula, parametrul se elimina
            elseif (!$value) unset($fields[$field]);
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        // - DIFERENTE (optional)
        $field = self::DIFERENTE;
        $value = &$fields[$field];
        $length=length($value);
        $e=null;
        if ($length) {
            // modul de repartizare sa fie valid
            if (!in_array($value, self::$criteriiDiferente)) $e = "Specificaţi modul de repartizare a diferenţelor de citire !";
            ####
            if ($e) $errors[$field]=$e;
        } else {
            unset($fields[$field]);
        }

        // - DOUA_FACTURI
        $field = self::DOUA_FACTURI;
        $value = &$fields[$field];
        if ($value) $value = '1';
        else unset($fields[$field]);

        return $errors;
    }
}

